


#include "stl_converter.h"


   

/// <summary>
/// 转换函数说明  ：
/// 以unt16的变量0x1234为例。这里0x12是高字节，0x34是低字节。（高字节数据的权重高，低字节数据的权重低）
/// （1）如果低字节存放在高地址，则为大端模式BigEdian    ：即0x34在高地址，0x12在低地址。
/// （2）如果低字节存放在低地址，则为小端模式LittleEndian：即0x12在高地址，0x34在低地址。
/// 例：
/// unt32 x = 0x00001234;		//十进制为4660
/// char tp = *((char*)&x);  //取tp等于x的低地址部分
/// //char tp=(char)x;      //这样也是一样的。
/// if (tp == 0x00)			//如果低地址部分取出的值是高字节的值，则为大端
/// if (tp == 0x34)			//如果低地址部分取出的值是低字节的值，则为小端
/// 下面的函数接口中，数组unt8* byteArry一律是小端模式，[0]保持低字节的值。
/// 前缀B_表示大端模式的数据与byteArry数组转换。
/// 前缀L_表示大端模式的数据与byteArry数组转换。
/// 
/// STM32单片机：小端模式。x86：小端。
/// STM8：大端。KEIL C51：大端。
/// ARM既可以工作在大端模式，也可以工作在小端模式。
/// 注意：大小端模式是和硬件有关的，即和芯片本身有关，IDE不能进行设置。
/// </summary>

/// <summary>
/// 浮点数转换为字节数组。
/// </summary>
/// <param name="num">大端模式的浮点数</param>
/// <param name="byteArry">转换后的字节数组，[0]是低字节</param>
void B_FloatToBytes(float num, unt8* byteArry)
{
	char* pchar = (char*)&num;
	byteArry[0] = pchar[3];
	byteArry[1] = pchar[2];
	byteArry[2] = pchar[1];
	byteArry[3] = pchar[0];
}
/// <summary>
/// unt32转换为字节数组。
/// </summary>
/// <param name="num">大端模式的unt32</param>
/// <param name="byteArry">转换后的字节数组，[0]是低字节</param>
void B_U32ToBytes(unt32 num, unt8* byteArry)
{
	char* pchar = (char*)&num;
	byteArry[0] = pchar[3];
	byteArry[1] = pchar[2];
	byteArry[2] = pchar[1];
	byteArry[3] = pchar[0];
}
/// <summary>
/// 字节数组转为浮点数
/// </summary>
/// <param name="byteArry">待转换的字节数组，[0]是低字节</param>
/// <returns>转换的结果。大端模式的浮点数</returns>
float B_BytesToFloat(unt8* byteArry)
{
	float num;
	char* pchar = (char*)&num;
	pchar[0] = byteArry[3];
	pchar[1] = byteArry[2];
	pchar[2] = byteArry[1];
	pchar[3] = byteArry[0];
	return num;
}
/// <summary>
/// 字节数组转为unt32
/// </summary>
/// <param name="byteArry">待转换的字节数组，[0]是低字节</param>
/// <returns>转换的结果，大端模式的unt32</returns>
unt32 B_BytesToU32(unt8* byteArry)
{
	unt32 num;
	char* pchar = (char*)&num;
	pchar[0] = byteArry[3];
	pchar[1] = byteArry[2];
	pchar[2] = byteArry[1];
	pchar[3] = byteArry[0];
	return num;
}


/// <summary>
/// 浮点数转换为字节数组。
/// </summary>
/// <param name="num">小端模式的浮点数</param>
/// <param name="byteArry">转换后的字节数组，[0]是低字节</param>
void L_FloatToBytes(float num, unt8* byteArry)
{
	char* pchar = (char*)&num;
	byteArry[0] = pchar[0];
	byteArry[1] = pchar[1];
	byteArry[2] = pchar[2];
	byteArry[3] = pchar[3];
}
/// <summary>
/// unt32转换为字节数组。
/// </summary>
/// <param name="num">小端模式的unt32</param>
/// <param name="byteArry">转换后的字节数组，[0]是低字节</param>
void L_U32ToBytes(unt32 num, unt8* byteArry)
{
	char* pchar = (char*)&num;
	byteArry[0] = pchar[0];
	byteArry[1] = pchar[1];
	byteArry[2] = pchar[2];
	byteArry[3] = pchar[3];
}
/// <summary>
/// 字节数组转为浮点数
/// </summary>
/// <param name="byteArry">待转换的字节数组，[0]是低字节</param>
/// <returns>转换的结果。小端模式的浮点数</returns>
float L_BytesToFloat(unt8* byteArry)
{
	float num;
	char* pchar = (char*)&num;
	pchar[0] = byteArry[0];
	pchar[1] = byteArry[1];
	pchar[2] = byteArry[2];
	pchar[3] = byteArry[3];
	return num;
}
/// <summary>
/// 字节数组转为unt32
/// </summary>
/// <param name="byteArry">待转换的字节数组，[0]是低字节</param>
/// <returns>转换的结果，小端模式的unt32</returns>
unt32 L_BytesToU32(unt8* byteArry)
{
	unt32 num;
	char* pchar = (char*)&num;
	pchar[0] = byteArry[0];
	pchar[1] = byteArry[1];
	pchar[2] = byteArry[2];
	pchar[3] = byteArry[3];
	return num;
}




////////////////////   下面是日期相关的代码                    ////////////////////////////////////////////////////////////////////////

#define FOURYEARDAY    1461              
// (365+365+365+366)  = 1461 。
//4年一个周期内的总天数。注意，四年一闰，百年不润，四百年又闰。
//2000年是闰年，但2100年不是。但我不一定能活到那时，所以就暂时不做优化。
//计算机的时间戳是1970/1/1 00:00:00开始计时的，32位无符号整型，可以用到2106年左右。

#define TIMEZONE    (8)  //北京时区调整，中国使用北京时区。如果换成其他国家，则设置成对应的时区。

static unt8 comm_month_day[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //平年 common year
static unt8 Leap_month_day[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //闰年 leap year

/// <summary>
/// 判断年份是否闰年
/// </summary>
/// <param name="year">待判断的年份</param>
/// <returns>1：闰年。0：平年。</returns>
unt8 isLeapYear(unt16 year)
{
    unt8 res = 0;
    if (year % 4 == 0) // 能够被4整除 
    {
        if ((year % 100 == 0) && (year % 400 != 0))	//能够被100整除，但是不能够被400整除 
        {
            res = 0;
        }
        else
        {
            res = 1;
        }
    }
    return res;
}


/// <summary>
/// 将Unix时间戳转换为北京时间
/// </summary>
/// <param name="unixTime">待转换的时间戳</param>
/// <param name="tempBeijing">转换后的北京时间的结构体</param>
void UnixTimeStp2Beijing(unt32 unixTime, rtc_time_t* tempBeijing)
{
    unt32 totleDayNum = 0, totleSecNum = 0;

    unt16 remainDayofYear = 0, tempSecond = 0, tempYear_Day = 0;
    unt8* pr;  //指向comm_month_day或Leap_month_day

    totleDayNum = unixTime / 86400; //总天数(注意加括号)  (24 * 60 * 60)=86400
    totleSecNum = unixTime % 86400; //当天剩余的秒速

    // 1.先计算时间 HH:MM:SS
    tempBeijing->ui8Hour = totleSecNum / 3600;
    tempSecond = totleSecNum % 3600;
    tempBeijing->ui8Minute = tempSecond / 60;
    tempBeijing->ui8Second = tempSecond % 60;

    // 2.对时间进行时区调整（注意：这里可能造成日期 +1）
    tempBeijing->ui8Hour += TIMEZONE;
    if (tempBeijing->ui8Hour > 23) {
        tempBeijing->ui8Hour -= 24;
        remainDayofYear++;  // 日期+1
    }

    // 3.计算哪一年
    tempBeijing->ui16Year = 1970 + (totleDayNum / FOURYEARDAY) * 4;   // 4年为一个周期
    remainDayofYear += totleDayNum % FOURYEARDAY;

    tempYear_Day = isLeapYear(tempBeijing->ui16Year) ? 366 : 365;
    while (remainDayofYear >= tempYear_Day)  // remainDayofYear比一年多，年份+1.
    {
        tempBeijing->ui16Year++;
        remainDayofYear -= tempYear_Day;
        tempYear_Day = isLeapYear(tempBeijing->ui16Year) ? 366 : 365;
    }

    // 4.计算哪一月的哪一天
    pr = isLeapYear(tempBeijing->ui16Year) ? Leap_month_day : comm_month_day;
    remainDayofYear++;          // 这里开始计算具体日期。remainDayofYear为 0 时其实是 1 号，所以这里要 +1
    tempBeijing->ui8Month = 0;
    while (remainDayofYear > *(pr + tempBeijing->ui8Month))
    {
        remainDayofYear -= *(pr + tempBeijing->ui8Month);
        tempBeijing->ui8Month++;
    }
    tempBeijing->ui8Month++;                       //month ,ui8Month为0时是1月，所以这里要加1.
	tempBeijing->ui8DayOfMonth = (unt8)remainDayofYear;  //day
}
//

/// <summary>
/// 将北京时间转换为Unix时间戳 
/// </summary>
/// <param name="beijingTime">待转换的时间</param>
/// <returns>转换后的时间戳</returns>
unt32 Beijing2UnixTimeStp(rtc_time_t* beijingTime)
{
    unt32 daynum = 0, SecNum = 0;          //保存北京时间到起始时间的天数
    unt16 tempYear = 1970, tempMonth = 0;

    //1.年的天数
    while (tempYear < beijingTime->ui16Year)
    {
        if (isLeapYear(tempYear)) {
            daynum += 366;
        }
        else {
            daynum += 365;
        }
        tempYear++;
        //   printfs("%d \r\n",daynum);
    }
    //2.月的天数
    if (isLeapYear(beijingTime->ui16Year)) { //闰年
        while (tempMonth < beijingTime->ui8Month - 1) {
            daynum += Leap_month_day[tempMonth];
            tempMonth++;
        }
    }
    else {
        while (tempMonth < beijingTime->ui8Month - 1) {
            daynum += comm_month_day[tempMonth];
            tempMonth++;
        }
    }

    //3.天数
    daynum += (beijingTime->ui8DayOfMonth - 1);

    //4.时分秒
    SecNum = daynum * 24 * 60 * 60; //s    
    SecNum += ((unt32)beijingTime->ui8Hour) * 60 * 60;
    SecNum += ((unt32)beijingTime->ui8Minute) * 60;
    SecNum += beijingTime->ui8Second;

    //5.时区调整
    SecNum -= TIMEZONE * 60 * 60;

    return SecNum;
}
//

/// <summary>
/// 将时间结构体转换成“月份/日期 时:分:秒” 的形式。
/// </summary>
/// <param name="beijingTime">时间结构体</param>
/// <param name="ch">转换后的字符串，“xx/xx xx:xx:xx ”共15个字节</param>
void rtc_time_t_To_string(rtc_time_t* beijingTime, char* ch)
{
    ch[0] = beijingTime->ui8Month / 10 + '0';
    ch[1] = beijingTime->ui8Month % 10 + '0';
    ch[2] = '/';
    ch[3] = beijingTime->ui8DayOfMonth / 10 + '0';
    ch[4] = beijingTime->ui8DayOfMonth % 10 + '0';
    ch[5] = ' ';
    ch[6] = beijingTime->ui8Hour / 10 + '0';
    ch[7] = beijingTime->ui8Hour % 10 + '0';
    ch[8] = ':';
    ch[9] = beijingTime->ui8Minute / 10 + '0';
    ch[10] = beijingTime->ui8Minute % 10 + '0';
    ch[11] = ':';
    ch[12] = beijingTime->ui8Second / 10 + '0';
    ch[13] = beijingTime->ui8Second % 10 + '0';
	ch[14] = 0;
}
//

/// <summary>
/// 将时间转化成 年份/月份/日期 时:分:秒 的形式。
/// </summary>
/// <param name="beijingTime">时间结构体</param>
/// <param name="ch">转换后的字符串，“xxxx/xx/xx xx:xx:xx ”共20个字节</param>
void rtc_time_t_To_string_YYYYMMDDhhmmss(rtc_time_t* beijingTime, char* ch)
{
    int year = beijingTime->ui16Year;

    ch[0] = year / 1000 + '0';
    year = year % 1000;
    ch[1] = year / 100 + '0';
    year = year % 100;
    ch[2] = year / 10 + '0';
    ch[3] = year % 10 + '0';
    ch[4] = '/';
    ch[5] = beijingTime->ui8Month / 10 + '0';
    ch[6] = beijingTime->ui8Month % 10 + '0';
    ch[7] = '/';
    ch[8] = beijingTime->ui8DayOfMonth / 10 + '0';
    ch[9] = beijingTime->ui8DayOfMonth % 10 + '0';
    ch[10] = ' ';
    ch[11] = beijingTime->ui8Hour / 10 + '0';
    ch[12] = beijingTime->ui8Hour % 10 + '0';
    ch[13] = ':';
    ch[14] = beijingTime->ui8Minute / 10 + '0';
    ch[15] = beijingTime->ui8Minute % 10 + '0';
    ch[16] = ':';
    ch[17] = beijingTime->ui8Second / 10 + '0';
    ch[18] = beijingTime->ui8Second % 10 + '0';
    ch[19] = 0;
}
//

/// <summary>
/// 将时间转化成 年份/月份/日期 时:分:秒 的形式。
/// </summary>
/// <param name="beijingTime">时间结构体</param>
/// <param name="ch">转换后的字符串，“xx/xx/xx xx:xx:xx ”共18个字节</param>
void rtc_time_t_To_string_YYMMDDhhmmss(rtc_time_t* beijingTime, char* ch)
{
    int year = beijingTime->ui16Year;

    year = year % 100;
    ch[0] = year / 10 + '0';
    ch[1] = year % 10 + '0';
    ch[2] = '/';
    ch[3] = beijingTime->ui8Month / 10 + '0';
    ch[4] = beijingTime->ui8Month % 10 + '0';
    ch[5] = '/';
    ch[6] = beijingTime->ui8DayOfMonth / 10 + '0';
    ch[7] = beijingTime->ui8DayOfMonth % 10 + '0';
    ch[8] = ' ';
    ch[9] = beijingTime->ui8Hour / 10 + '0';
    ch[10] = beijingTime->ui8Hour % 10 + '0';
    ch[11] = ':';
    ch[12] = beijingTime->ui8Minute / 10 + '0';
    ch[13] = beijingTime->ui8Minute % 10 + '0';
    ch[14] = ':';
    ch[15] = beijingTime->ui8Second / 10 + '0';
    ch[16] = beijingTime->ui8Second % 10 + '0';
    ch[17] = 0;
}
//


/// <summary>
/// 转化成 年/月/日 的形式
/// </summary>
/// <param name="beijingTime">时间结构体</param>
/// <param name="ch">转换后的字符串，“xx/xx/xx ”共9个字节</param>
void rtc_time_t_To_yyMMdd(rtc_time_t* beijingTime, char* ch)
{
	ch[0] = (beijingTime->ui16Year % 100) / 10 + '0';
	ch[1] = beijingTime->ui16Year % 10 + '0';
	ch[2] = '/';
	ch[3] = beijingTime->ui8Month / 10 + '0';
	ch[4] = beijingTime->ui8Month % 10 + '0';
	ch[5] = '/';
	ch[6] = beijingTime->ui8DayOfMonth / 10 + '0';
	ch[7] = beijingTime->ui8DayOfMonth % 10 + '0';
	ch[8] = 0;
}

/// <summary>
/// 转化成 年/月/日 的形式
/// </summary>
/// <param name="beijingTime">时间结构体</param>
/// <param name="ch">转换后的字符串，“xx:xx:xx ”共9个字节</param>
void rtc_time_t_To_HHmmss(rtc_time_t* beijingTime, char* ch)
{
	ch[0] = beijingTime->ui8Hour / 10 + '0';
	ch[1] = beijingTime->ui8Hour % 10 + '0';
	ch[2] = ':';
	ch[3] = beijingTime->ui8Minute / 10 + '0';
	ch[4] = beijingTime->ui8Minute % 10 + '0';
	ch[5] = ':';
	ch[6] = beijingTime->ui8Second / 10 + '0';
	ch[7] = beijingTime->ui8Second % 10 + '0';
	ch[8] = 0;
}
//




////////////////    下面是字符串的转换               //////////////////////////////////////////////////////////////////



/// <summary>
/// 匹配字符串。看str是否包含msg。  str会自动忽略头部的空格
/// </summary>
/// <param name="msg">已知字符串</param>
/// <param name="str">待匹配字符串</param>
/// <returns>是否匹配 </returns>
bool str_match(const char* msg, char* str)
{
	int i = 0;
	int j=0;
	while(str[j]==' ')j++;
	
	while (msg[i] != 0)
	{
		if (msg[i] == str[j]){
			j++;
			i++;
		}
		else return false;
	}
	return true;
}


/*
 static 修饰函数 - 静态函数
函数默认是有外部链接属性的，但是被 static 修饰后，会使得函数失去外部链接属性，变成内部链接属性。
所以 static 修饰的函数只能在自己所在的.c 文件内部使用，不能在其他文件中使用。
其他c文件有同名的文件，也可以正常编译。
*/

/// <summary>
/// 整型的指数运算。返回 base^exponent。
/// </summary>
/// <param name="base">底数</param>
/// <param name="exponent">指数</param>
/// <returns>运算结果</returns>
static int powi(int base, int exponent)
{
	int i;
	int a = 1;
	for (i = 0; i < exponent; i++) {
		a *= base;
	}
	return a;
}
//

/// <summary>
/// 将字符串形式的浮点数转换成浮点类型。
/// 这是迭代函数。
/// 会忽略字符串开头的空格。遇到非法字符会退出，如果字符串不是浮点数，会返回0。
/// 流程：移除空格，是否符号，移除空格，提取整数，提取小数。遇到非法字符立即推出。
/// 如果返回负数，说明没有提取到数字就遇到非法字符，说明提取数字失败，返回数据的绝对值还可以继续索引。
/// </summary>
/// <param name="str">待转换的字符串</param>
/// <param name="f">提取的浮点数。</param>
/// <returns>当前字符串指针索引。即提取一个浮点数后的字符串位置。</returns>
int str_to_float(char* str, float* f)
{
	//提取字符串中的浮点数。	
	//浮点数是5个长度。
	char* ostr = str;
	float num = 0;       //数值
	unsigned char sign = 0;  //sign==0正，==1负
	bool is_get_digit = false;
	//移除前面的空格。
	while (*str == ' ')
	{
		str++;
	}
	if (*str == '+') {
		sign = 0;
		str++;
	}
	else if (*str == '-') {
		sign = 1;
		str++;
	}
	//移除前面的空格。
	while (*str == ' ')
	{
		str++;
	}

	while (str[0] != '\0')             //获取整数部分
	{
		if (*str == 0x2E)               //遇到小数点时跳出
			break;
		if (*str < '0' || *str>'9')      //遇到非有效字符时返回字符串已转换的数值
		{
			if (sign == 0) *f = num;
			else *f = -num;
			return is_get_digit ? (str - ostr) : (ostr - str);
		}
		is_get_digit = true;
		num = num * 10 + (*str - '0');
		str++;
	}

	if (*str == 0x2E)                  //获取小数部分
	{
		int i = 10;
		str++;
		while (str[0] != '\0')
		{
			if (*str < '0' || *str>'9')          //遇到非有效字符时返回字符串已转换的数值
			{
				if (sign == 0) *f = num;
				else *f = -num;
				return is_get_digit ? (str - ostr) : (ostr - str);
			}
			is_get_digit = true;
			num = num + ((float)(*str - '0')) / i;
			i = i * 10;
			str++;
		}
	}
	if (sign == 0) *f = num;
	else *f = -num;
	return is_get_digit ? (str - ostr) : (ostr - str);
}

/// <summary>
/// 将字符串形式的整形转换成整型
/// 这是迭代函数。
/// 会忽略字符串开头的空格。遇到非法字符会退出，如果字符串不是浮点数，会返回0。
/// 如果返回负数，说明没有提取到数字就遇到非法字符，说明提取数字失败，返回数据的绝对值还可以继续索引。
/// </summary>
/// <param name="str">待转换的字符串</param>
/// <param name="i">提取的整数</param>
/// <returns>当前字符串指针索引。即提取一个浮点数后的字符串位置。</returns>
int str_to_int(char* str, int* i)
{
	char* ostr = str;
	bool is_get_digit = false;

	int  num = 0;
	unsigned char sign = 0;  //sign==0正，==1负
	//移除前面的空格。
	while (*str == ' ')
	{
		str++;
	}
	if (*str == '+') {
		sign = 0;
		str++;
	}
	else if (*str == '-') {
		sign = 1;
		str++;
	}
	//移除前面的空格。
	while (*str == ' ')
	{
		str++;
	}

	if (str[0] == '0' && str[1] == 'x') { //如果是十六进制
		str += 2;
		while (*str != 0)  // 遍历
		{
			if ((*str >= '0' && *str <= '9')) // 合法字符判定
			{
				is_get_digit = true;
				num = num * 16 + (*str - '0');
			}
			else if ((*str >= 'a' && *str <= 'f')) // 合法字符判定
			{
				is_get_digit = true;
				num = num * 16 + (*str - 'a') + 10;
			}
			else if ((*str >= 'A' && *str <= 'F')) // 合法字符判定
			{
				is_get_digit = true;
				num = num * 16 + (*str - 'A') + 10;
			}
			else // 字符串中含有非法字符，返回已经转换的整数
			{
				if (sign == 0)
				{
					*i = num;
				}
				else {
					*i = -num;
				}
				return is_get_digit ? (str - ostr) : (ostr - str);

			}
			str++;
		}
	}
	else {
		while (*str != 0)  // 遍历
		{
			if ((*str >= '0' && *str <= '9')) // 合法字符判定
			{
				is_get_digit = true;
				num = num * 10 + (*str - '0');
			}
			else // 字符串中含有非法字符
			{
				if (sign == 0) {
					*i = num;
				}
				else {
					*i = -num;
				}
				return is_get_digit ? (str - ostr) : (ostr - str);

			}
			str++;
		}
	}


	if (sign == 0) {
		*i = num;
	}
	else {
		*i = -num;
	}
	return is_get_digit ? (str - ostr) : (ostr - str);

}



/////////////////////////////////////////////////////////////////////////////////////////////


/// <summary>
/// 整形转字符串。
/// </summary>
/// <param name="val">待转换的数据</param>
/// <param name="str">转换的字符串，右对齐。如果字符串长度不够，只记录高位。</param>
/// <param name="str_width">字符串的宽度。包含一个符号位。实际显示的数字只有str_width-1位。</param>
/// <param name="radix">转换的进制。16进制内都可以</param>
/// <returns>数字转换成字符串的长度</returns>
void int_to_str(int val, char* str, int str_width, unsigned radix)
{
	//整数位数不确定，但可以立刻知道个位是什么，所以这里先将字符串倒过来
	char digval;    //中间变量，记录位的值。
	char sign;      //符号位
	char tstr[12];  //临时字符串。转换后的数字先放这里，再转换到str。32的int型只有10位。因此足够了。
	int len = 0;    //记录已转换的字符串tstr的长度
	if (val >= 0) {
		sign = 0;
	}
	else {
		val = -val;
		sign = 1;
	}
	do {
		digval = val % radix;
		val /= radix;
		//如果这个位的值大于9，用字母abcdef表示
		if (digval > 9) tstr[len] = (char)(digval + 'A' - 10);   // A是65，a是97，
		else tstr[len] = (char)(digval + '0');
		len++;
	} while (val > 0);
	if (sign == 0) {
		tstr[len] = ' ';
		len++;
	}
	else {
		tstr[len] = '-';
		len++;
	}

	//下面将tstr的内容复制到str
	if (len > str_width) {
		int i = 0;
		for (i = 0; i < str_width; i++) {
			str[i] = tstr[len - i - 1];
		}
	}
	else {   //右对齐，左边用空格补齐。
		int i = 0;
		for (i = 0; i < str_width - len; i++) {
			str[i] = ' ';
		}
		for (i = str_width - len; i < str_width; i++) {
			str[i] = tstr[str_width - i - 1];
		}
	}
}
//

/// <summary>
/// 整形转字符串。
/// </summary>
/// <param name="val">待转换的数据</param>
/// <param name="str">转换的字符串，左对齐。如果字符串长度不够，只记录高位。</param>
/// <param name="str_width">字符串的宽度。包含一个符号位。实际显示的数字只有str_width-1位。</param>
/// <param name="radix">转换的进制。16进制内都可以</param>
/// <returns>数字转换成字符串的长度,(不包括右侧填充空格的字符)</returns>
int int_to_str_left(int val, char* str, int str_width, unsigned radix)
{
	//整数位数不确定，但可以立刻知道个位是什么，所以这里先将字符串倒过来
	char digval;    //中间变量，记录位的值。
	char sign;      //符号位
	char tstr[12];  //临时字符串。转换后的数字先放这里，再转换到str。32的int型只有10位。因此足够了。
	int len = 0;    //记录已转换的字符串tstr的长度
	if (val >= 0) {
		sign = 0;
	}
	else {
		val = -val;
		sign = 1;
	}
	do {
		digval = val % radix;
		val /= radix;
		//如果这个位的值大于9，用字母abcdef表示
		if (digval > 9)
			tstr[len] = (char)(digval + 'A' - 10);   // A是65，a是97，
		else
			tstr[len] = (char)(digval + '0');

		len++;
	} while (val > 0);
	if (sign == 0) {
		tstr[len] = ' ';
		len++;
	}
	else {
		tstr[len] = '-';
		len++;
	}

	//下面将tstr的内容复制到str
	if (len > str_width) {
		int i = 0;
		for (i = 0; i < str_width; i++) {
			str[i] = tstr[len - i - 1];
		}
	}
	else {     //左对齐，右边填充空格。
		int i = 0;
		for (i = 0; i < len; i++) {
			str[i] = tstr[len - i - 1];
		}
		for (i = len; i < str_width; i++) {
			str[i] = ' ';
		}
	}
	return len;
}
//

/// <summary>
/// 整形转字符串。
/// </summary>
/// <param name="val">待转换的数据</param>
/// <param name="str">转换的字符串，右对齐。如果字符串长度不够，只记录高位。</param>
/// <param name="str_width">字符串的宽度。</param>
/// <param name="radix">转换的进制。16进制内都可以</param>
/// <returns>数字转换成字符串的长度</returns>
void uint_to_str(unsigned int val, char* str, int str_width, unsigned radix)
{
	//整数位数不确定，但可以立刻知道个位是什么，所以这里先将字符串倒过来
	char digval;    //中间变量，记录位的值。
	char tstr[12];  //临时字符串。转换后的数字先放这里，再转换到str。32的int型只有10位。因此足够了。
	int len = 0;    //记录已转换的字符串tstr的长度
	do {
		digval = val % radix;
		val /= radix;
		//如果这个位的值大于9，用字母abcdef表示
		if (digval > 9) tstr[len] = (char)(digval + 'A' - 10);   // A是65，a是97，
		else tstr[len] = (char)(digval + '0');
		len++;
	} while (val > 0);
	//下面将tstr的内容复制到str
	if (len > str_width) {
		int i = 0;
		for (i = 0; i < str_width; i++) {
			str[i] = tstr[len - i - 1];
		}
	}
	else {   //右对齐，左边用空格补齐。
		int i = 0;
		for (i = 0; i < str_width - len; i++) {
			str[i] = ' ';
		}
		for (i = str_width - len; i < str_width; i++) {
			str[i] = tstr[str_width - i - 1];
		}
	}
}
//

/// <summary>
/// 整形转字符串。
/// </summary>
/// <param name="val">待转换的数据</param>
/// <param name="str">转换的字符串，左对齐。如果字符串长度不够，只记录高位。</param>
/// <param name="str_width">字符串的宽度。包含一个符号位。实际显示的数字只有str_width-1位。</param>
/// <param name="radix">转换的进制。16进制内都可以</param>
/// <returns>数字转换成字符串的长度</returns>
int uint_to_str_left(unsigned int val, char* str, int str_width, unsigned radix)
{
	//整数位数不确定，但可以立刻知道个位是什么，所以这里先将字符串倒过来
	char digval;    //中间变量，记录位的值。
	char tstr[12];  //临时字符串。转换后的数字先放这里，再转换到str。32的int型只有10位。因此足够了。
	int len = 0;    //记录已转换的字符串tstr的长度
	do {
		digval = val % radix;
		val /= radix;
		//如果这个位的值大于9，用字母abcdef表示
		if (digval > 9)
			tstr[len] = (char)(digval + 'A' - 10);   // A是65，a是97，
		else
			tstr[len] = (char)(digval + '0');

		len++;
	} while (val > 0);
	//下面将tstr的内容复制到str
	if (len > str_width) {
		int i = 0;
		for (i = 0; i < str_width; i++) {
			str[i] = tstr[len - i - 1];
		}
	}
	else {     //左对齐，右边填充空格。
		int i = 0;
		for (i = 0; i < len; i++) {
			str[i] = tstr[len - i - 1];
		}
		for (i = len; i < str_width; i++) {
			str[i] = ' ';
		}
	}
	return len;

}
//

/// <summary>
/// 整形转字符串。
/// </summary>
/// <param name="val">待转换的数据</param>
/// <param name="str">转换的字符串，右对齐。如果字符串长度不够，只记录高位。</param>
/// <param name="str_width">字符串的宽度。包含一个符号位,一个小数点。实际显示的数字只有str_width-2位。</param>
/// <param name="decimal">小数点显示的位数</param>
/// <returns>数字转换成字符串的长度</returns>
void float_to_str(float val, char* str, int str_width, int decimal)
{
	//整数位数不确定，但可以立刻知道个位是什么，所以这里先将字符串倒过来
	char digval;    //中间变量，记录位的值。
	char sign;      //符号位
	char tstr[18];  //临时字符串。转换后的数字先放这里，再转换到str。32的int型只有10位，浮点数最多6位小数。18位够了。
	int len = 0;    //记录已转换的字符串tstr的长度
	int ival;
	if (val >= 0) {
		sign = 0;
	}
	else {
		val = -val;
		sign = 1;
	}
	if (decimal > 6)decimal = 6;  //浮点数最多有6位小数。

	//先转换小数部分：
	{
		//先按照显示的小数位数把浮点数的小数部分放大，变成整数，然后在右边第decimal位的位置加上小数点。
		int ex = powi(10, decimal);
		ival = (int)((val - (int)val) * ex + 0.5f);   //四舍五入
		if (ival / ex >= 1) {
			val += (ival / ex);   //四舍五入如果进位到了整数，则需要给整数部分增加。
			ival = ival % ex;
		}
		do {
			digval = ival % 10;
			ival /= 10;
			tstr[len] = (char)(digval + '0');
			len++;
		} while (ival > 0);
		//这里注意：前面需要填充0字符。不然会出错。
		while (len < decimal)
		{
			tstr[len] = '0';
			len++;
		}
		tstr[len] = '.';
		len++;
	}
	//转换整数部分
	ival = val;
	do {
		digval = ival % 10;
		ival /= 10;
		tstr[len] = (char)(digval + '0');
		len++;
	} while (ival > 0);
	if (sign == 0) {
		tstr[len] = ' ';
		len++;
	}
	else {
		tstr[len] = '-';
		len++;
	}

	//下面将tstr的内容复制到str
	if (len > str_width) {
		int i = 0;
		for (i = 0; i < str_width; i++) {
			str[i] = tstr[len - i - 1];
		}
	}
	else {   //右对齐，左边用空格补齐。
		int i = 0;
		for (i = 0; i < str_width - len; i++) {
			str[i] = ' ';
		}
		for (i = str_width - len; i < str_width; i++) {
			str[i] = tstr[str_width - i - 1];
		}
	}
}
//

/// <summary>
/// 整形转字符串。
/// </summary>
/// <param name="val">待转换的数据</param>
/// <param name="str">转换的字符串，左对齐。如果字符串长度不够，只记录高位。</param>
/// <param name="str_width">字符串的宽度。包含一个符号位,一个小数点。实际显示的数字只有str_width-2位。</param>
/// <param name="decimal">小数点显示的位数</param>
/// <returns>数字转换成字符串的长度</returns>
int float_to_str_left(float val, char* str, int str_width, int decimal)
{
	//整数位数不确定，但可以立刻知道个位是什么，所以这里先将字符串倒过来
	char digval;    //中间变量，记录位的值。
	char sign;      //符号位
	char tstr[18];  //临时字符串。转换后的数字先放这里，再转换到str。32的int型只有10位，浮点数最多6位小数。18位够了。
	int len = 0;    //记录已转换的字符串tstr的长度
	int ival;
	if (val >= 0) {
		sign = 0;
	}
	else {
		val = -val;
		sign = 1;
	}
	if (decimal > 6)decimal = 6;  //浮点数最多有6位小数。

	//先转换小数部分：
	{
		//先按照显示的小数位数把浮点数的小数部分放大，变成整数，然后在右边第decimal位的位置加上小数点。
		int ex = powi(10, decimal);
		ival = (int)((val - (int)val) * ex + 0.5f);   //四舍五入
		if (ival / ex >= 1) {
			val += (ival / ex);   //四舍五入如果进位到了整数，则需要给整数部分增加。
			ival = ival % ex;
		}
		do {
			digval = ival % 10;
			ival /= 10;
			tstr[len] = (char)(digval + '0');
			len++;
		} while (ival > 0);
		//这里注意：前面需要填充0字符。不然会出错。
		while (len < decimal)
		{
			tstr[len] = '0';
			len++;
		}
		tstr[len] = '.';
		len++;
	}
	//转换整数部分
	ival = val;
	do {
		digval = ival % 10;
		ival /= 10;
		tstr[len] = (char)(digval + '0');
		len++;
	} while (ival > 0);
	if (sign == 0) {
		tstr[len] = ' ';
		len++;
	}
	else {
		tstr[len] = '-';
		len++;
	}

	//下面将tstr的内容复制到str
	if (len > str_width) {
		int i = 0;
		for (i = 0; i < str_width; i++) {
			str[i] = tstr[len - i - 1];
		}
	}
	else {     //左对齐，右边填充空格。
		int i = 0;
		for (i = 0; i < len; i++) {
			str[i] = tstr[len - i - 1];
		}
		for (i = len; i < str_width; i++) {
			str[i] = ' ';
		}
	}
	return len;

}
//




void test_data_converter_a()
{
	char str[20] = "                   ";
	float Epsilon_2 = 0.00001f;
	int test_times = 30 / Epsilon_2;   // 大概 300 万次测试。

	double sumf = 0, sumf2 = 0;
	for (int i = -test_times; i < test_times; i++) {
		float f = i * Epsilon_2;
		// float_to_str(f, str, 15, 5);
		
		float_to_str_left(f, str, 15, 5);
		float f2;
		str_to_float(str, &f2);

		sumf += (f);
		sumf2 += (f2);

		if (ABS(f - f2) > Epsilon_2) {
			printfs(" \r\n    err %f  %f          !!!!!!! ", f, f2);
		}
		if (i % 100000 == 0) {
			printfs(" \r\n sum  %f  %f  ", sumf, sumf2);
		}
	}
	printfs(" \r\n sum  %f  %f  ", sumf, sumf2);


	for (int i = -test_times; i < test_times; i++) {
		int f = i;
		// int_to_str(f, str, 15, 5);
		
		int_to_str_left(f, str, 15, 10);
		int f2;	
		str_to_int(str, &f2);

		sumf += (f);
		sumf2 += (f2);

		if (ABS(f - f2) > Epsilon_2) {
			printfs(" \r\n    err %f  %f          !!!!!!! ", f, f2);
		}
		if (i % 100000 == 0) {
			printfs(" \r\n sum  %f  %f  ", sumf, sumf2);
		}
	}
	printfs(" \r\n sum  %f  %f  ", sumf, sumf2);




}


void test_data_converter()
{
	char str[20] = "                   ";

	int test_times = 30;// / Epsilon;   // 大概 300 万次测试。

	double sumf = 0, sumf2 = 0;
	for (int i = -test_times; i < test_times; i++) {
		float f = i * 0.1; // Epsilon;
		// float_to_str(f, str, 15, 5);

		float_to_str_left(f, str, 15, 5);
		float f2;
		str_to_float(str, &f2);

		sumf += (f);
		sumf2 += (f2);

		//if (ABS(f - f2) > Epsilon) 
		{
			printfs(" \r\n    err %f  %f          !!!!!!! ", f, f2);
		}
		if (i % 100000 == 0) 
		{
			printfs(" \r\n sum  %f  %f  ", sumf, sumf2);
		}
	}
	printfs(" \r\n sum  %f  %f  ", sumf, sumf2);


	for (int i = -test_times; i < test_times; i++) {
		int f = i;
		// int_to_str(f, str, 15, 5);

		int_to_str_left(f, str, 15, 10);
		int f2;
		str_to_int(str, &f2);

		sumf += (f);
		sumf2 += (f2);

		//if (ABS(f - f2) > Epsilon) 
		{
			printfs(" \r\n    err %d  %d          !!!!!!! ", f, f2);
		}
		if (i % 100000 == 0) {
			printfs(" \r\n sum  %f  %f  ", sumf, sumf2);
		}
	}
	printfs(" \r\n sum  %f  %f  ", sumf, sumf2);




}





